/**
 * 
 */
package com.designpattern.design.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

/**
 * 代理模式
 * @author zhangyang
 *
 */
public class ProxyTest {
public static void main(String[] args) {
	TeacherDao dao = new TeacherDao();
	//静态代理
	StaticTeacherProxy proxy = new StaticTeacherProxy(dao);
	proxy.teach();
	JDKTeacherProxy teacherProxy = new JDKTeacherProxy(dao);
	IteacherDao JDKproxy = (IteacherDao)teacherProxy.getProxyInstance();
	JDKproxy.teach();
//	System.out.println(JDKproxy.getClass());
	CglibTeachDao teachDao = new CglibTeachDao();
	CglibTeachDao cglibTeacherProxy = (CglibTeachDao)new CglibTeacherProxy(teachDao).getProxyInstance();
	cglibTeacherProxy.teach();
}
}

interface IteacherDao{
	void teach();
}
class TeacherDao implements IteacherDao{

	@Override
	public void teach() {
		// TODO Auto-generated method stub
		System.out.println("原老师正在授课");
	}
	
}
/**
 * 静态代理
 * @author zhangyang
 *
 */
class StaticTeacherProxy implements IteacherDao{

	private IteacherDao dao;
	
	
	public StaticTeacherProxy(IteacherDao dao) {
		super();
		this.dao = dao;
	}


	@Override
	public void teach() {
		// TODO Auto-generated method stub
		System.out.println("代理开始");
		dao.teach();
		System.out.println("代理结束");
	}
	
}
/**
 * 动态代理实现-本质 JDKproxy包的api->底层:反射
 * @author zhangyang
 *
 */
class JDKTeacherProxy{
	//原对象 object类型的 由构造器构造进来
	private Object target;

	public JDKTeacherProxy(Object target) {
		super();
		this.target = target;
	}
	
	public Object getProxyInstance() {
		/**
		 * Proxy.newProxyInstance 方法详解
		 * loader-指定当前目标使用的的类加载器 获取加载器方法
		 * interfaces 目标接口实现的接口类型 使用泛型的方式确认类型
		 * h invocationHandler 事件处理 执行目标对象处理时，触发目标事件的方法
		 * 会把当前执行的目标对象方法作为参数传入
		 */
		 return Proxy.newProxyInstance(target.getClass().getClassLoader(), 
				target.getClass().getInterfaces(), new InvocationHandler() {
					
			 /**
			  * proxy 代理对象通常是接口
			  * method 方法
			  * args 参数
			  */
					@Override
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						// TODO Auto-generated method stub
						System.out.println("JDK代理开始");
						//通过反射机制调用方法
						Object invoke = method.invoke(target, args);
						return invoke;
					}
				});
	}
}


class CglibTeachDao{
	void teach() {
		System.out.println("Cglib代理，不需要接口");
	}
}
/**
 * Cglib代理-不使用接口实现代理
 * @author zhangyang
 *
 */
class CglibTeacherProxy implements MethodInterceptor{

	
	private Object target;
	
	public CglibTeacherProxy(Object target) {
		super();
		this.target = target;
	}

	/**
	 * 返回目标对象target的代理对象-也就是该类的子类
	 * @return
	 */
	public Object getProxyInstance() {
		//1设置一个工具类
		Enhancer enhancer = new Enhancer();
		//2设置工具类的父类
		enhancer.setSuperclass(target.getClass());
		//3设置回调函数
		enhancer.setCallback(this);
		//4创建子类对象
		return enhancer.create();
	}
	
	//public 
	/**
	 * 重写方法，是被代理对象方法的调用
	 */
	@Override
	public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
		// TODO Auto-generated method stub
		System.out.println("cglib代理启动");
		Object returnVal = arg1.invoke(target, arg2);
		System.out.println("cglib代理结束");
		return returnVal;
	}
	
}